/* fastPathPatTree.h - Definitions for the Patricia tree Fastpath cache */

/* Copyright 1984 - 2004 Wind River Systems, Inc. */

/*
modification history
--------------------
01h,28may04,niq  Merging from base6 label POST_ITER5_FRZ16_REBASE
01g,04nov03,rlm  Ran batch header path update for header re-org.
01f,07aug01,niq  Adding a lookup version with netmask + coding convention
                 compliance.
01e,29jun01,spm  removed use of deleted metric for obsolete OSPF implementation
01d,02may01,niq  Correcting mod history
01c,01may01,niq  Copied over from tor2_0.open_stack branch
01b,20mar01,niq  Adding comments
01a,29jan01,niq  written
*/

/*
DESCRIPTION
 
This include file contains definitions used by the Patricia tree
Fastpath cache implementation (fastPathPatTree.c)
It also includes MACROS that allow the Fastpath module (fastPathIp.c) to
access the fields on the cache entry without needing to know the
structure of the cache entry
 
INCLUDE FILES:
*/

#ifndef __INCfastPathPatTreeh
#define __INCfastPathPatTreeh

/* includes */

#include <net/route.h>
#include <net/radix.h>
#include <private/fastPathPatTreeP.h>

/* defines */

/* Maps to the Cache interface functions */

#define CACHE_INIT			ptCacheInit
#define CACHE_DESTROY			ptCacheDestroy
#define CACHE_ENTRY_ADD			ptCacheEntryAdd
#define CACHE_ENTRY_PREFORMED_ADD	ptCacheEntryInternalAdd
#define CACHE_ENTRY_DEL			ptCacheEntryDel
#define CACHE_ENTRY_FREE			ptCacheEntryFree
#define CACHE_LOOKUP			ptCacheLookup
#define CACHE_LOOKUP_NM			ptCacheNmLookup
#define CACHE_WALK			ptCacheWalk
#define CACHE_DESTROY			ptCacheDestroy

/* Definitions for Cache entry flags */

#define FF_ENTRY_FLAG_UP		RTF_UP		/* 1 */
#define FF_ENTRY_FLAG_INDIRECT	RTF_GATEWAY	/* 2 */
#define FF_ENTRY_FLAG_HOST	RTF_HOST	/* 4 */
#define FF_ENTRY_FLAG_INTF_ROUTE	RTF_REJECT	/* 8 */
#define FF_ENTRY_FLAG_MAC	RTF_LLINFO	/* 0x400 */
#define FF_ENTRY_FLAG_VALID	RTF_PROTO2	/* 0x4000 */
#define FF_ENTRY_FLAG_COMPLETE	RTF_PROTO1	/* 0x8000 */

/* Use the following macros to access the fields of the cache entry */

#define GET_CACHE_ENTRY_DEST_ADDR(pRt)		(rt_key (pRt))
#define GET_CACHE_ENTRY_NET_MASK(pRt)		(rt_mask (pRt))
#define GET_CACHE_ENTRY_GATE_ADDR(pRt)		((pRt)->rt_gateway)

#define GET_CACHE_ENTRY_MAC_ADDR(pRt)		(((pRt)->rt_gateway)->sa_data)
#define SET_CACHE_ENTRY_MAC_ADDR(pRt, macAddr, len) \
    bcopy ((unsigned char *)macAddr, \
	   (unsigned char *)GET_CACHE_ENTRY_MAC_ADDR (pRt), len)

#define GET_CACHE_ENTRY_GATE_ROUTE(pRt)		((pRt)->rt_gwroute)
#define SET_CACHE_ENTRY_GATE_ROUTE(pRt, x)		((pRt)->rt_gwroute = x)

#define GET_CACHE_ENTRY_ROUTE_METRIC(pRt)		1

#define GET_CACHE_ENTRY_IF_MTU(pRt)	((pRt)->rt_rmx.value1)
#define SET_CACHE_ENTRY_IF_MTU(pRt, x)		((pRt)->rt_rmx.value1 = x)

#define GET_CACHE_ENTRY_IF_INDEX(pRt)		((int)((pRt)->rt_llinfo))
#define SET_CACHE_ENTRY_IF_INDEX(pRt, x)		((pRt)->rt_llinfo = (caddr_t)x)

#define GET_CACHE_ENTRY_MUX_COOKIE(pRt)		((pRt)->rt_ifa)
#define SET_CACHE_ENTRY_MUX_COOKIE(pRt, x)		((pRt)->rt_ifa = x)

#define GET_CACHE_ENTRY_IF_COOKIE(pRt)		((pRt)->rt_ifp)
#define SET_CACHE_ENTRY_IF_COOKIE(pRt, x)		((pRt)->rt_ifp = x)

#define GET_CACHE_ENTRY_USE_COUNT(pRt)		((pRt)->rt_use)
#define SET_CACHE_ENTRY_USE_COUNT(pRt, x)		((pRt)->rt_use = x)
#define INC_CACHE_ENTRY_USE_COUNT(pRt)	(++GET_CACHE_ENTRY_USE_COUNT (pRt))
#define DEC_CACHE_ENTRY_USE_COUNT(pRt)	(--GET_CACHE_ENTRY_USE_COUNT (pRt))

#define GET_CACHE_ENTRY_FLAGS(pRt)			((pRt)->rt_flags)
#define SET_CACHE_ENTRY_FLAGS(pRt, x)		((pRt)->rt_flags = x)

#define MARK_CACHE_ENTRY_UP(pRt) \
    SET_CACHE_ENTRY_FLAGS (pRt, GET_CACHE_ENTRY_FLAGS (pRt) | FF_ENTRY_FLAG_UP)
#define MARK_CACHE_ENTRY_NOTUP(pRt) \
    SET_CACHE_ENTRY_FLAGS (pRt, GET_CACHE_ENTRY_FLAGS (pRt) & \
			   ~FF_ENTRY_FLAG_UP)

#define MARK_CACHE_ENTRY_COMPLETE(pRt) \
    SET_CACHE_ENTRY_FLAGS (pRt, GET_CACHE_ENTRY_FLAGS (pRt) | \
			   FF_ENTRY_FLAG_COMPLETE)
#define MARK_CACHE_ENTRY_INCOMPLETE(pRt) \
    SET_CACHE_ENTRY_FLAGS (pRt, GET_CACHE_ENTRY_FLAGS (pRt) & \
			   ~FF_ENTRY_FLAG_COMPLETE)

#define MARK_CACHE_ENTRY_VALID(pRt) \
    SET_CACHE_ENTRY_FLAGS (pRt, GET_CACHE_ENTRY_FLAGS (pRt) | \
			   FF_ENTRY_FLAG_VALID)
#define MARK_CACHE_ENTRY_INVALID(pRt) \
    SET_CACHE_ENTRY_FLAGS (pRt, GET_CACHE_ENTRY_FLAGS (pRt) & \
			   ~FF_ENTRY_FLAG_VALID)

#define MARK_CACHE_ENTRY_INDIRECT(pRt) \
    SET_CACHE_ENTRY_FLAGS (pRt, GET_CACHE_ENTRY_FLAGS (pRt) | \
			   FF_ENTRY_FLAG_INDIRECT)
#define MARK_CACHE_ENTRY_DIRECT(pRt) \
    SET_CACHE_ENTRY_FLAGS (pRt, GET_CACHE_ENTRY_FLAGS (pRt) & \
			   ~FF_ENTRY_FLAG_INDIRECT)

#define GET_CACHE_ENTRY_REFCNT(pRt)		((pRt)->rt_refcnt)
#define SET_CACHE_ENTRY_REFCNT(pRt, x)	((pRt)->rt_refcnt = x)
#define INC_CACHE_ENTRY_REFCNT(pRt)	(++GET_CACHE_ENTRY_REFCNT (pRt))
#define DEC_CACHE_ENTRY_REFCNT(pRt)	(--GET_CACHE_ENTRY_REFCNT (pRt))

/* Is Cache entry a direct route or an Indirect route */

#define IS_CACHE_ENTRY_DIRECT(pRt) \
  ((GET_CACHE_ENTRY_FLAGS (pRt) & FF_ENTRY_FLAG_INDIRECT) == 0)
#define IS_CACHE_ENTRY_MAC(pRt)  	 \
  ((GET_CACHE_ENTRY_FLAGS (pRt) & FF_ENTRY_FLAG_MAC))
#define IS_CACHE_ENTRY_COMPLETE(pRt) \
  ((GET_CACHE_ENTRY_FLAGS (pRt) & FF_ENTRY_FLAG_COMPLETE))

/* Is the Gateway route set, as opposed to just being marked gateway */

#define IS_GATEWAY_ROUTE_SET(pRt)		GET_CACHE_ENTRY_GATE_ROUTE (pRt)

#define IS_CACHE_ENTRY_UP(pRt)		(GET_CACHE_ENTRY_FLAGS (pRt) & \
					 FF_ENTRY_FLAG_UP)
#define IS_CACHE_ENTRY_VALID(pRt)		(GET_CACHE_ENTRY_FLAGS (pRt) & \
					 FF_ENTRY_FLAG_VALID)

/* Is the cache entry an Interface route */

#define IS_CACHE_ENTRY_INTF_ROUTE(pRt)	(GET_CACHE_ENTRY_FLAGS (pRt) & \
					 FF_ENTRY_FLAG_INTF_ROUTE)

/*
 * An entry is COMPLETE_AND_VALID if it is both
 *   valid : the interface is up and enabled for fast forwarding   AND
 *   COMPLETE : The forwarding information is available
 */

#define IS_CACHE_ENTRY_COMPLETE_AND_VALID(pRt)	 \
    ((GET_CACHE_ENTRY_FLAGS (pRt) & \
      (FF_ENTRY_FLAG_VALID | FF_ENTRY_FLAG_COMPLETE)) == \
     (FF_ENTRY_FLAG_VALID | FF_ENTRY_FLAG_COMPLETE))


/* 
 * If it is a direct entry, is the entry valid, else if the
 * gateway route is set, is the gateway route entry valid
 */

#define IS_FULL_CACHE_ENTRY_VALID(pRt) \
    (IS_CACHE_ENTRY_DIRECT (pRt) ? IS_CACHE_ENTRY_VALID (pRt) : \
     (IS_GATEWAY_ROUTE_SET (pRt) && \
      IS_CACHE_ENTRY_VALID (GET_CACHE_ENTRY_GATE_ROUTE (pRt))))


/* 
 * Get the cache entry that contains  the MAC address. For a direct
 * route, it is that entry itself. For an indirect route it is the
 * gateway's MAC entry
 */

#define GET_MAC_CACHE_ENTRY(pRt) \
     (IS_CACHE_ENTRY_DIRECT (pRt) ? pRt : (GET_CACHE_ENTRY_GATE_ROUTE (pRt)))

/*
 * Given an entry pRt, sets pNewRt to the entry that can be used
 * for forwarding. If the entry cannot be used for forwarding, pNewRt
 * is set to NULL
 */

#define GET_USABLE_ENTRY(pNewRt, pRt) \
    { \
    if (IS_CACHE_ENTRY_COMPLETE_AND_VALID (pRt)) \
	{ \
	if ((IS_GATEWAY_ROUTE_SET (pRt))) \
	    { \
	    if (!IS_CACHE_ENTRY_COMPLETE_AND_VALID ((pNewRt = \
				     GET_CACHE_ENTRY_GATE_ROUTE (pRt)))) \
		pNewRt = NULL; \
	    } \
	else \
	    pNewRt = pRt; \
	} \
    else \
	pNewRt = NULL; \
    }



/* typedef */

/* Prototype for the user defined function that ptCacheWalk invokes */

typedef int (* PT_CACHE_WALK_FUNC_ID) (void *, void *);


/* function declarations */

IMPORT void * ptCacheInit (unsigned char * pMemPtr, int numRoutes, int proto);
IMPORT STATUS ptCacheDestroy (void *pCookie);
IMPORT CACHE_ENTRY_ID ptCacheEntryAdd (void * pCookie, 
				       struct sockaddr * pDstIpAddr, 
				       struct sockaddr * pNetMask, 
				       struct sockaddr * pGateIpAddr);
IMPORT STATUS ptCacheEntryInternalAdd (void * pCookie, 
				       CACHE_ENTRY_ID pCacheEntry, 
				       struct sockaddr * pDstIpAddr, 
				       struct sockaddr * pNetMask);
IMPORT CACHE_ENTRY_ID ptCacheEntryDel (void * pCookie, 
				       struct sockaddr * pDstIpAddr, 
				       struct sockaddr * pDstNetMask, 
				       BOOL free);
IMPORT void ptCacheEntryFree (CACHE_ENTRY_ID pCacheEntry);
IMPORT STATUS ptCacheWalk (void * pCookie, PT_CACHE_WALK_FUNC_ID pUsrFunc, 
			   void * pArg);
IMPORT CACHE_ENTRY_ID ptCacheLookup (void * pCookie, struct sockaddr * pDstIpAddr,
				     BOOL fromPktSndPath);
IMPORT CACHE_ENTRY_ID ptCacheNmLookup (void * pCookie, 
				       struct sockaddr * pDstIpAddr,
				       struct sockaddr * pNetmask, 
				       BOOL fromPktSndPath);

#endif /* __INCfastPathPatTreeh */
